package web.reader;

import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Shimu
 * @date 16-Sep-2012
 */
public class Webpage2 {

    /**
     * Captures an element that is closed in the start tag
     */
    private static final Pattern PATTERN_EMPTY_ELEMENT =
            Pattern.compile("<(\\w+)(.*)/>");

    /**
     * Captures an element that is not closed in the start tag
     * (i.e. has an end tag).
     */
    private static final Pattern PATTERN_NON_EMPTY_ELEMENT =
            Pattern.compile("<(\\w+)(.*)>([^<>]*)</(\\w+)>");

    /**
     * Captures an element that is not closed in the start tag
     * (i.e. has an end tag).
     */
    private static final Pattern PATTERN_ATTRIBUTE =
            Pattern.compile("^([^=]+)=\"([^\"]*?)\"");

    /**
     * Captures a comment inside an html document.
     */
    private static final Pattern PATTERN_COMMENT =
            Pattern.compile("<!-- (.*) -->");

    private final ArrayList<HtmlElement> elements;

    private final ArrayList<String> others;

    public Webpage2(String url) {
        this.elements = new ArrayList<HtmlElement>();
        this.others = new ArrayList<String>();
        extractElements(url);
    }

    private ArrayList<HtmlAttribute> extractAttributes(String line) {
        ArrayList<HtmlAttribute> attributes = new ArrayList<HtmlAttribute>();
        Matcher m = PATTERN_ATTRIBUTE.matcher(line);
        while (m.find()) {
            attributes.add(new HtmlAttribute(m.group(1).trim(),
                    m.group(2).trim()));
            m.region(m.end(), line.length());
        }
        return attributes;
    }

    private void extractElements(String url) {
        try {
            ArrayList<String> content = readURL(url);
            Matcher m;
            for (String line : content) {
                line = line.trim();
                if ((m = PATTERN_EMPTY_ELEMENT.matcher(line)).matches()) {
                    elements.add(new HtmlElement(m.group(1),
                            extractAttributes(m.group(2))));

                } else if ((m = PATTERN_NON_EMPTY_ELEMENT.matcher(line)).matches()) {
                    elements.add(new HtmlElement(m.group(1), m.group(3),
                            extractAttributes(m.group(2))));
                } else if ((m = PATTERN_COMMENT.matcher(line)).matches()) {
                                        
                } else {
                    others.add(line);
                }
            }
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
            System.exit(1);
        } catch (IOException ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Given a URL, attempt to connect to the URL and return the content
     * of the URL. 
     * 
     * @param <T> the return type of the ContentAccumulator
     * @param url the URL to retrieve information from
     * @param ac the ContentAccumulator used to retrieve information from the
     * URL
     * @return 
     * 
     * @throws MalformedURLException if the given URL was invalid
     * @throws IOException if an error occurred while trying to connect or
     * retrieve information from the given URL.
     */
    private static ArrayList<String> readURL(String url) throws
            MalformedURLException, IOException {
        URL webpage = new URL(url);
        BufferedReader in =
                new BufferedReader(new InputStreamReader(webpage.openStream()));

        ArrayList<String> list = new ArrayList<String>();
        String line;
        while ((line = in.readLine()) != null) {
            list.add(line);
        }

        in.close();
        return list;
    }

    /**
     * @return the elements
     */
    public ArrayList<HtmlElement> getElements() {
        return elements;
    }

    public ArrayList<String> getOthers() {
        return others;
    }
}
